package org.demos.server.pojo;

import cn.hutool.core.date.DateUtil;
import lombok.Data;
import lombok.ToString;

/**
 * 代表了一个服务实例
 * 里面包含了一个服务实例的所有信息
 * 比如说服务名称、ip地址、hostname、端口号、服务实例id
 * 还有就是契约信息（Lease）: 每一次心跳就像在续约一般
 *
 * @author bing.zhang06@hand-china.com 2021/10/26 15:49
 **/
@Data
@ToString
public class ServiceInstance {
    /**
     * 判断一个服务实例不再存活的周期
     */
    private static final Long NOT_ALIVE_PERIOD = 90 * 1000L;

    /**
     * 服务名称
     */
    private String serviceName;
    /**
     * ip地址
     */
    private String ip;
    /**
     * 主机名
     */
    private String hostname;
    /**
     * 端口号
     */
    private int port;
    /**
     * 服务实例id
     */
    private String serviceInstanceId;
    /**
     * 契约
     */
    private Lease lease;

    public ServiceInstance() {
        this.lease = new Lease();
    }

    /**
     * 服务续约
     */
    public void renew() {
        this.lease.renew();
    }

    /**
     * 服务实例是否存活
     *
     * @return
     */
    public Boolean isAlive() {
        return this.lease.isAlive();
    }

    /**
     * 契约
     * 维护了一个服务实例跟当前的这个注册中心之间的联系
     * 包括了心跳的时间，创建的时间，等等
     *
     * @author ztranscript
     */
    private class Lease {
        /**
         * 最近一次心跳的时间
         */
        private Long latestHeartbeatTime = System.currentTimeMillis();

        /**
         * 续约，你只要发送一次心跳，就相当于把register-client和register-server之间维护的一个契约
         * 进行了续约，我还存活着，我们俩的契约可以维持着
         */
        public void renew() {
            this.latestHeartbeatTime = System.currentTimeMillis();
            System.out.println("服务实例【" + serviceInstanceId + "】，" + DateUtil.now() + "进行续约：" + latestHeartbeatTime);
        }

        /**
         * 判断当前服务实例的契约是否还存活
         *
         * @return
         */
        public Boolean isAlive() {
            Long currentTime = System.currentTimeMillis();
            if (currentTime - latestHeartbeatTime > NOT_ALIVE_PERIOD) {
                System.out.println("服务实例【" + serviceInstanceId + "】，不再存活");
                return false;
            }
            System.out.println("服务实例【" + serviceInstanceId + "】，保持存活");
            return true;
        }
    }
}
